#include "ExampleScene.h"

#include <graphics/utils.h>
#include <graphics/image2d.h>
#include <assert.h>
#include <math.h>

ExampleScene::ExampleScene()
    : Yam3DScene()
    , m_camera(0)
    , m_mesh(0)
    , m_baseMap(0)
    , m_lightMap(0)
    , m_program(0)
    , m_totalTime(0.0f)
{
    // Create cool vertex and fragment shaders.
    QGLShader *vshader = new QGLShader(QGLShader::Vertex);
    char vShaderStr[] =
        "uniform mat4 matModelViewProj;                                 \n"
        "attribute vec4 a_position;                                     \n"
        "attribute vec2 a_texCoord;                                     \n"
        "varying vec2 vTexCoord;                                        \n"
        "void main()                                                    \n"
        "{                                                              \n"
        "   gl_Position = matModelViewProj * a_position;                \n"
        "   vTexCoord    = a_texCoord;                                  \n"
        "}                                                              \n";
    vshader->compileSourceCode(vShaderStr);

    QGLShader *fshader = new QGLShader(QGLShader::Fragment);
    char fShaderStr[] =
        "varying vec2 vTexCoord;                                        \n"
        "uniform sampler2D sBaseMap;                                    \n"
        "uniform sampler2D sLightMap;                                   \n"
        "void main()                                                    \n"
        "{                                                              \n"
        "  vec4 baseColor = texture2D( sBaseMap, vTexCoord );           \n"
        "  vec4 lightColor = texture2D( sLightMap, vTexCoord );         \n"
        "  gl_FragColor = baseColor * (lightColor + 0.25);              \n"
        "}                                                              \n";
    fshader->compileSourceCode(fShaderStr);

    assert( m_program == 0 );
    m_program = new QGLShaderProgram();
    m_program->addShader(vshader);
    m_program->addShader(fshader);
    m_program->link();
    m_program->bind();


    // Create camera for our scene.
    assert( m_camera == 0 );
    m_camera = new graphics::Camera();
    m_camera->setTranslation( QVector3D(0,0,1.0f) );

    m_mesh = graphics::genPlane( 16, 16 );

    graphics::Image2D baseMapImg(":/assets/basemap.png");
    graphics::Image2D lightMapImg(":/assets/lightmap.png");
    m_baseMap = new render::Texture2D(&baseMapImg,false);
    m_lightMap = new render::Texture2D(&lightMapImg,false);
}

ExampleScene::~ExampleScene()
{
}

void ExampleScene::resize(int width, int height)
{
    m_camera->setPerspective(60.0f, float(width)/float(height), 0.5f, 45.5f);
    glViewport( 0,0, width, height);
}

void ExampleScene::update(float deltaTime)
{
    m_totalTime += deltaTime;

    m_mesh->setOrientation( QQuaternion::fromAxisAndAngle(0,0,1,m_totalTime*60) );
}

void ExampleScene::render()
{
    // Set render states
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

    // Use the program object
    m_program->bind();

    // Set the base map texture unit to 0
    m_baseMap->bind(0);
    // Override texture filtering
    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    m_program->setUniformValue("sBaseMap", 0 );

    // Set the light map texture unit to 0
    m_lightMap->bind(1);
    // Override texture filtering
    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    m_program->setUniformValue("sLightMap", 1 );

    // Render mesh (sets attributes and draws the object)
    m_mesh->renderGeometryWithShader(m_program,m_camera);
}


